<!DOCTYPE html>
<!--

// Copyright 2011 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

-->
<html>
<head>
<title></title>
<script src="../../../../third_party/closure-library/closure/goog/base.js"></script>
<script>
// NOTE: base.js and all goog.require statements must be in JS script blocks
// NOTE: because they use document.write to add new script tags in place
goog.require('goog.testing.jsunit');
</script>
<script src="../../../../src/traceur.js"></script>
</head>
<body>
<script>

var ParseTree = traceur.syntax.trees.ParseTree;
var ParseTreeType = traceur.syntax.trees.ParseTreeType;

function testParseTreeType() {
  assertEquals('PROGRAM', ParseTreeType.PROGRAM);
}

function testParseTree() {
  var tree = new ParseTree('type', 'location');
  assertEquals('type', tree.type);
  assertEquals('location', tree.location);
}

function testParseTree2() {
  var tree = new ParseTree(ParseTreeType.NULL_TREE, 'location');
  assertEquals(ParseTreeType.NULL_TREE, tree.type);
  assertEquals(true, tree.isNull());
  assertEquals(false, tree.isPattern());
}

function validateTree(constr, type, fields) {
  function TestTree() {
    constr.apply(this, fields);
  }
  TestTree.prototype = Object.create(constr.prototype);

  var tree = new TestTree();
  assertEquals(type, tree.type);

  // Verify that each of the fields has been set to the correct value
  for (var i = 0; i < fields.length; i++) {
    var f = fields[i];
    assertEquals(f, tree[f]);
  }

  // Test JSON (and location stripping)
  var roundtrip = JSON.parse(JSON.stringify(tree, ParseTree.stripLocation));
  assert(roundtrip.location === undefined);
  for (var i = 1; i < fields.length; i++) {
    var f = fields[i];
    assertEquals(f, roundtrip[f]);
  }
}

function testNullTree() {
  // NullTree is a singleton so it needs its own test
  var tree = new traceur.syntax.trees.NullTree();
  assertEquals('NULL_TREE', tree.type);
  assertEquals(null, tree.location);
  var tree2 = new traceur.syntax.trees.NullTree();
  assertEquals(tree, tree2);
}

function testTreeConstructors() {
  validateTree(traceur.syntax.trees.ArgumentList,
      ParseTreeType.ARGUMENT_LIST,
      ['location', 'args']);

  validateTree(traceur.syntax.trees.ArrayLiteralExpression,
      ParseTreeType.ARRAY_LITERAL_EXPRESSION,
      ['location', 'elements']);

  validateTree(traceur.syntax.trees.ArrayPattern,
      ParseTreeType.ARRAY_PATTERN,
      ['location', 'elements']);

  validateTree(traceur.syntax.trees.AwaitStatement,
      ParseTreeType.AWAIT_STATEMENT,
      ['location', 'identifier', 'expression']);

  validateTree(traceur.syntax.trees.BinaryOperator,
      ParseTreeType.BINARY_OPERATOR,
      ['location', 'left', 'operator', 'right']);

  validateTree(traceur.syntax.trees.Block,
      ParseTreeType.BLOCK,
      ['location', 'statements']);

  validateTree(traceur.syntax.trees.BreakStatement,
      ParseTreeType.BREAK_STATEMENT,
      ['location', 'name']);

  validateTree(traceur.syntax.trees.CallExpression,
      ParseTreeType.CALL_EXPRESSION,
      ['location', 'operand', 'args']);

  validateTree(traceur.syntax.trees.CaseClause,
      ParseTreeType.CASE_CLAUSE,
      ['location', 'expression', 'statements']);

  validateTree(traceur.syntax.trees.Catch,
      ParseTreeType.CATCH,
      ['location', 'binding', 'catchBody']);

  validateTree(traceur.syntax.trees.ClassDeclaration,
      ParseTreeType.CLASS_DECLARATION,
      ['location', 'name', 'superClass', 'elements']);

  validateTree(traceur.syntax.trees.ClassExpression,
      ParseTreeType.CLASS_EXPRESSION,
      ['location', 'name', 'superClass', 'elements']);

  validateTree(traceur.syntax.trees.CommaExpression,
      ParseTreeType.COMMA_EXPRESSION,
      ['location', 'expressions']);

  validateTree(traceur.syntax.trees.ConditionalExpression,
      ParseTreeType.CONDITIONAL_EXPRESSION,
      ['location', 'condition', 'left', 'right']);

  validateTree(traceur.syntax.trees.ContinueStatement,
      ParseTreeType.CONTINUE_STATEMENT,
      ['location', 'name']);

  validateTree(traceur.syntax.trees.DebuggerStatement,
      ParseTreeType.DEBUGGER_STATEMENT,
      ['location']);

  validateTree(traceur.syntax.trees.DefaultClause,
      ParseTreeType.DEFAULT_CLAUSE,
      ['location', 'statements']);

  validateTree(traceur.syntax.trees.DoWhileStatement,
      ParseTreeType.DO_WHILE_STATEMENT,
      ['location', 'body', 'condition']);

  validateTree(traceur.syntax.trees.EmptyStatement,
      ParseTreeType.EMPTY_STATEMENT,
      ['location']);

  validateTree(traceur.syntax.trees.ExportDeclaration,
      ParseTreeType.EXPORT_DECLARATION,
      ['location', 'declaration']);

  validateTree(traceur.syntax.trees.ExportMappingList,
    ParseTreeType.EXPORT_MAPPING_LIST,
    ['location', 'paths']);

  validateTree(traceur.syntax.trees.ExportMapping,
    ParseTreeType.EXPORT_MAPPING,
    ['location', 'moduleExpression', 'specifierSet']);

  validateTree(traceur.syntax.trees.ExportSpecifier,
    ParseTreeType.EXPORT_SPECIFIER,
    ['location', 'lhs', 'rhs']);

  validateTree(traceur.syntax.trees.ExportSpecifierSet,
    ParseTreeType.EXPORT_SPECIFIER_SET,
    ['location', 'specifiers']);

  validateTree(traceur.syntax.trees.ExpressionStatement,
      ParseTreeType.EXPRESSION_STATEMENT,
      ['location', 'expression']);

  validateTree(traceur.syntax.trees.Finally,
      ParseTreeType.FINALLY,
      ['location', 'block']);

  validateTree(traceur.syntax.trees.ForOfStatement,
      ParseTreeType.FOR_OF_STATEMENT,
      ['location', 'initializer', 'collection', 'body']);

  validateTree(traceur.syntax.trees.ForInStatement,
      ParseTreeType.FOR_IN_STATEMENT,
      ['location', 'initializer', 'collection', 'body']);

  validateTree(traceur.syntax.trees.FormalParameterList,
      ParseTreeType.FORMAL_PARAMETER_LIST,
      ['location', 'parameters']);

  validateTree(traceur.syntax.trees.ForStatement,
      ParseTreeType.FOR_STATEMENT,
      ['location', 'initializer', 'condition', 'increment', 'body']);

  validateTree(traceur.syntax.trees.FunctionDeclaration,
      ParseTreeType.FUNCTION_DECLARATION,
      ['location', 'name', 'isGenerator',
       'formalParameterList', 'functionBody']);

  validateTree(traceur.syntax.trees.GetAccessor,
      ParseTreeType.GET_ACCESSOR,
      ['location', 'propertyName', 'body']);

  validateTree(traceur.syntax.trees.IdentifierExpression,
      ParseTreeType.IDENTIFIER_EXPRESSION,
      ['location', 'identifierToken']);

  validateTree(traceur.syntax.trees.IfStatement,
      ParseTreeType.IF_STATEMENT,
      ['location', 'condition', 'ifClause', 'elseClause']);

  validateTree(traceur.syntax.trees.ImportDeclaration,
      ParseTreeType.IMPORT_DECLARATION,
      ['location', 'importPathList']);

  validateTree(traceur.syntax.trees.ImportBinding,
      ParseTreeType.IMPORT_BINDING,
      ['location', 'moduleExpression', 'importSpecifierSet']);

  validateTree(traceur.syntax.trees.ImportSpecifier,
      ParseTreeType.IMPORT_SPECIFIER,
      ['location', 'lhs', 'rhs']);

  validateTree(traceur.syntax.trees.ImportSpecifierSet,
      ParseTreeType.IMPORT_SPECIFIER_SET,
      ['location', 'specifiers']);

  validateTree(traceur.syntax.trees.LabelledStatement,
      ParseTreeType.LABELLED_STATEMENT,
      ['location', 'name', 'statement']);

  validateTree(traceur.syntax.trees.LiteralExpression,
      ParseTreeType.LITERAL_EXPRESSION,
      ['location', 'literalToken']);

  validateTree(traceur.syntax.trees.MemberExpression,
      ParseTreeType.MEMBER_EXPRESSION,
      ['location', 'operand', 'memberName']);

  validateTree(traceur.syntax.trees.MemberLookupExpression,
      ParseTreeType.MEMBER_LOOKUP_EXPRESSION,
      ['location', 'operand', 'memberExpression']);

  validateTree(traceur.syntax.trees.MissingPrimaryExpression,
      ParseTreeType.MISSING_PRIMARY_EXPRESSION,
      ['location', 'nextToken']);

  validateTree(traceur.syntax.trees.ModuleDeclaration,
      ParseTreeType.MODULE_DECLARATION,
      ['location', 'specifiers']);

  validateTree(traceur.syntax.trees.ModuleDefinition,
      ParseTreeType.MODULE_DEFINITION,
      ['location', 'name', 'elements']);

  validateTree(traceur.syntax.trees.ModuleExpression,
      ParseTreeType.MODULE_EXPRESSION,
      ['location', 'reference', 'identifiers']);

  validateTree(traceur.syntax.trees.ModuleRequire,
      ParseTreeType.MODULE_REQUIRE,
      ['location', 'url']);

  validateTree(traceur.syntax.trees.ModuleSpecifier,
      ParseTreeType.MODULE_SPECIFIER,
      ['location', 'identifier', 'expression']);

  validateTree(traceur.syntax.trees.NewExpression,
      ParseTreeType.NEW_EXPRESSION,
      ['location', 'operand', 'args']);

  validateTree(traceur.syntax.trees.ObjectLiteralExpression,
      ParseTreeType.OBJECT_LITERAL_EXPRESSION,
      ['location', 'propertyNameAndValues']);

  validateTree(traceur.syntax.trees.ObjectPatternField,
      ParseTreeType.OBJECT_PATTERN_FIELD,
      ['location', 'identifier', 'element']);

  validateTree(traceur.syntax.trees.ObjectPattern,
      ParseTreeType.OBJECT_PATTERN,
      ['location', 'fields']);

  validateTree(traceur.syntax.trees.ParenExpression,
      ParseTreeType.PAREN_EXPRESSION,
      ['location', 'expression']);

  validateTree(traceur.syntax.trees.PostfixExpression,
      ParseTreeType.POSTFIX_EXPRESSION,
      ['location', 'operand', 'operator']);

  validateTree(traceur.syntax.trees.Program,
      ParseTreeType.PROGRAM,
      ['location', 'programElements']);

  validateTree(traceur.syntax.trees.PropertyMethodAssignment,
      ParseTreeType.PROPERTY_METHOD_ASSIGNMENT,
      ['location', 'name', 'isGenerator', 'formalParameterList',
       'functionBody']);

  validateTree(traceur.syntax.trees.PropertyNameAssignment,
      ParseTreeType.PROPERTY_NAME_ASSIGNMENT,
      ['location', 'name', 'value']);

  validateTree(traceur.syntax.trees.PropertyNameShorthand,
      ParseTreeType.PROPERTY_NAME_SHORTHAND,
      ['location', 'name']);

  validateTree(traceur.syntax.trees.RequiresMember,
      ParseTreeType.REQUIRES_MEMBER,
      ['location', 'name']);

  validateTree(traceur.syntax.trees.RestParameter,
      ParseTreeType.REST_PARAMETER,
      ['location', 'identifier']);

  validateTree(traceur.syntax.trees.ReturnStatement,
      ParseTreeType.RETURN_STATEMENT,
      ['location', 'expression']);

  validateTree(traceur.syntax.trees.SetAccessor,
      ParseTreeType.SET_ACCESSOR,
      ['location', 'propertyName', 'parameter', 'body']);

  validateTree(traceur.syntax.trees.SpreadExpression,
      ParseTreeType.SPREAD_EXPRESSION,
      ['location', 'expression']);

  validateTree(traceur.syntax.trees.SpreadPatternElement,
      ParseTreeType.SPREAD_PATTERN_ELEMENT,
      ['location', 'lvalue']);

  validateTree(traceur.syntax.trees.SuperExpression,
      ParseTreeType.SUPER_EXPRESSION,
      ['location']);

  validateTree(traceur.syntax.trees.SwitchStatement,
      ParseTreeType.SWITCH_STATEMENT,
      ['location', 'expression', 'caseClauses']);

  validateTree(traceur.syntax.trees.ThisExpression,
      ParseTreeType.THIS_EXPRESSION,
      ['location']);

  validateTree(traceur.syntax.trees.ThrowStatement,
      ParseTreeType.THROW_STATEMENT,
      ['location', 'value']);

  validateTree(traceur.syntax.trees.TryStatement,
      ParseTreeType.TRY_STATEMENT,
      ['location', 'body', 'catchBlock', 'finallyBlock']);

  validateTree(traceur.syntax.trees.UnaryExpression,
      ParseTreeType.UNARY_EXPRESSION,
      ['location', 'operator', 'operand']);

  validateTree(traceur.syntax.trees.VariableDeclarationList,
      ParseTreeType.VARIABLE_DECLARATION_LIST,
      ['location', 'declarationType', 'declarations']);

  validateTree(traceur.syntax.trees.VariableDeclaration,
      ParseTreeType.VARIABLE_DECLARATION,
      ['location', 'lvalue', 'initializer']);

  validateTree(traceur.syntax.trees.VariableStatement,
      ParseTreeType.VARIABLE_STATEMENT,
      ['location', 'declarations']);

  validateTree(traceur.syntax.trees.WhileStatement,
      ParseTreeType.WHILE_STATEMENT,
      ['location', 'condition', 'body']);

  validateTree(traceur.syntax.trees.WithStatement,
      ParseTreeType.WITH_STATEMENT,
      ['location', 'expression', 'body']);

  validateTree(traceur.syntax.trees.YieldStatement,
      ParseTreeType.YIELD_STATEMENT,
      ['location', 'expression', 'isYieldFor']);
}

</script>
</body>
</html>
